package sql

import (
	"LogisticsPort/model"
	"database/sql"
	sql2 "database/sql"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/schema"
	"io/ioutil"
	"math/rand"
	"net/http"
	"os"
	"path"
	"strconv"
	"strings"
	"time"
)

const (
	ADD    = "新增"
	DELETE = "删除"
	GET    = "获取"
	UPDATE = "修改"
)

type HandlerFunc func(*gin.Context, *gorm.DB) interface{}

func InitGormDB() *gorm.DB {
	sqlPath := strings.Join([]string{name, ":", password, "@tcp(", ip, ":", port, ")/", dbName,
		"?charset=utf8&parseTime=True&loc=Local"}, "")
	fmt.Println(sqlPath)
	db, err := gorm.Open(mysql.Open(sqlPath), &gorm.Config{
		NamingStrategy: schema.NamingStrategy{SingularTable: true},
	})

	if nil != err {
		fmt.Println("Open Database Err:", err)
		return nil
	}
	sqlDB, err := db.DB()
	if err != nil {
		fmt.Println("Open Database Err:", err)
		return nil
	}
	//  设置空闲连接池的最大连接数。
	sqlDB.SetMaxIdleConns(10)
	//  设置到数据库的最大打开连接数。
	sqlDB.SetMaxOpenConns(100)
	sqlDB.SetConnMaxLifetime(30)

	if err = sqlDB.Ping(); err != nil {
		fmt.Println("open database fail:", err)
		return nil
	}
	fmt.Println("connect success")
	return db
}

func ImageSave(c *gin.Context, fileStr string) string {
	return save(c, "images[]", fileStr)
}

func FileSave(c *gin.Context, fileStr string) string {
	return save(c, "files[]", fileStr)
}

func save(c *gin.Context, field string, fileStr string) string {
	var netStr string
	if field == "images[]" {
		netStr = "netImageStr"
	} else {
		netStr = "netFileStr"
	}
	result := c.PostForm(netStr)
	form, err := c.MultipartForm()
	if err != nil {
		if result == "" {
			return "[]"
		}
		arr := strings.Split(result, ",")
		str, _ := json.Marshal(arr)
		result = string(str)
		return result
	}
	files := form.File[field]
	if files != nil {
		index := strings.LastIndex(fileStr, "/")
		folder := fileStr[:index+1]

		dir := "./upload/" + folder
		if err := os.MkdirAll(dir, 0666); err != nil {
			//创建文件夹失败
			c.JSON(http.StatusBadRequest, model.BaseJsonBean{Code: 400, Message: "上传失败"})
		}
		for _, file := range files {
			suffix := path.Ext(file.Filename) //文件后缀
			var fileName string
			if field == "images[]" {
				fileName = fileStr[index+1:] + "_" + strconv.Itoa(rand.Intn(5000)+rand.Intn(5000)) + suffix
			} else {
				fileName = file.Filename
			}
			filePath := dir + fileName
			err := c.SaveUploadedFile(file, filePath)
			if err != nil {
				c.JSON(http.StatusBadRequest, model.BaseJsonBean{Code: 400, Message: "上传失败"})
				return result
			}
			if result == "" {
				result += "/" + folder + fileName
			} else {
				result += ",/" + folder + fileName
			}
		}
	}
	if result == "" {
		return "[]"
	}
	arr := strings.Split(result, ",")
	str, _ := json.Marshal(arr)
	result = string(str)
	return result
}

func DBHandleDelete(c *gin.Context, value interface{}) {
	DBHandle(c, DELETE, func(context *gin.Context, db *gorm.DB) interface{} {
		id := c.Query("id")
		db.Where("id = ?", id).Delete("Customer")
		if db == nil && db.RowsAffected > 0 {
			return nil
		}
		c.JSON(http.StatusOK, &model.BaseJsonBean{
			Code: 200, Message: DELETE + "失败",
		})
		return nil
	})
}

func DBHandle(c *gin.Context, text string, handle HandlerFunc) {
	db := InitGormDB()
	dbHandle := handle(c, db)
	sqlDB, err := db.DB()
	if err != nil {
		fmt.Println("Database Err:", err)
		c.JSON(http.StatusInternalServerError, &model.BaseJsonBean{
			Code: 500, Message: "服务器异常",
		})
		return
	}
	defer func(sqlDB *sql2.DB) {
		err := sqlDB.Close()
		if err != nil {
			fmt.Println("Close Database Err:", err)
			c.JSON(http.StatusInternalServerError, &model.BaseJsonBean{
				Code: 500, Message: "服务器异常",
			})
			return
		}
	}(sqlDB)
	//新增或编辑失败
	if (text == ADD || text == UPDATE) && dbHandle == nil {
		return
	}
	c.JSON(http.StatusOK, &model.BaseJsonBean{
		Code: 200, Message: text + "成功", Data: dbHandle,
	})
}

func StrFormatList(str string) []string {
	var list []string
	err := json.Unmarshal([]byte(str), &list)
	if err != nil {
		fmt.Println("json error: ", err)
	}
	return list
}

/*func DataBind[T](c *gin.Context, t T) T {
	if err := c.Bind(&t); err != nil {
		c.JSON(http.StatusBadRequest, model.BaseJsonBean{Code: 400, Message: "请求参数错误"})
		return t
	}
	return t
}*/

/*
参数错误
*/
func ParamError(c *gin.Context, msg string) interface{} {
	c.JSON(http.StatusBadRequest, model.BaseJsonBean{Code: 400, Message: msg})
	return nil
}

func RequestError(c *gin.Context) interface{} {
	return ParamError(c, "请求参数错误")
}

func ErrorDelete(c *gin.Context) interface{} {
	c.JSON(http.StatusInternalServerError, model.BaseJsonBean{Code: 500, Message: "服务器异常，删除失败"})
	return nil
}

func InitDB() *sql.DB {
	////构建连接信息
	path := strings.Join([]string{name, ":", password, "@tcp(", ip, ":", port, ")/", dbName, "?charset=utf8"}, "")
	fmt.Println(path)

	//打开数据库，前面是驱动名称，所以要导入:mysql驱动github.com/go-sql-driver/mysql
	DB, err := sql.Open("mysql", path)
	if nil != err {
		fmt.Println("Open Database Err:", err)
		return nil
	}
	// 设置数据库的最大连接数
	DB.SetConnMaxLifetime(30 * time.Second)
	// 设置数据库最大的闲置连接数
	DB.SetMaxIdleConns(10)
	if err = DB.Ping(); err != nil {
		fmt.Println("open database fail:", err)
		return nil
	}
	// 验证连接
	fmt.Println("connect success")
	return DB
}

func ShowImage(c *gin.Context) {
	folder := c.Param("folder")
	imageName := c.Param("image")

	image := "/project/upload/" + folder + "/" + imageName
	//image := "D:\\gowork\\LogisticsPort\\upload\\" + folder + "\\" + imageName
	file, err := ioutil.ReadFile(image)
	if file == nil {
		fmt.Println("image display:", err)
		c.JSON(http.StatusNotFound, model.BaseJsonBean{Code: 404, Message: "未找到图片"})
		return
	}
	str, _ := c.Writer.WriteString(string(file))
	fmt.Println(str)
}

func ThirdLevelDirectory(c *gin.Context) {

	module := c.Param("module")
	folder := c.Param("folder")
	imageName := c.Param("image")
	var image string
	if imageName == "/" {
		image = "/project/upload/" + module + "/" + folder
	} else {
		image = "/project/upload/" + module + "/" + folder + "/" + imageName
	}
	//image := "D:\\gowork\\LogisticsPort\\upload\\" + folder + "\\" + imageName
	file, err := ioutil.ReadFile(image)
	if file == nil {
		fmt.Println("image display:", err)
		c.JSON(http.StatusNotFound, model.BaseJsonBean{Code: 404, Message: "未找到图片"})
		return
	}
	length := len(file)
	c.Header("content-length", strconv.Itoa(length))
	str, _ := c.Writer.WriteString(string(file))
	fmt.Println(str)
}
